
package com.petot.claude.gwtc.client;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.Place;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.AcceptsOneWidget;

/**
 * <code>PageAbstractActivity</code>
 */
public abstract class PageAbstractActivity<V extends PageAbstractView<D>,D extends PageAbstractView.Delegate> extends AbstractActivity {

    /**
     * Manages the pages
     */
    protected final PlaceController placeController;

    /**
     * Event Bus, common to the whole application
     */
    protected EventBus eventBus;

    /**
     * View linked to this activity
     */
    protected final V view;

    /**
     * View's container
     */
    protected AcceptsOneWidget display;

    /**
     * Constructeur
     * @param pRequests
     * @param placeController
     * @param view
     */
    @SuppressWarnings( "unchecked" )
    public PageAbstractActivity( final PlaceController placeController, final V view ) {
        this.placeController = placeController;
        this.view = view;
        if (view == null) {
            throw new IllegalStateException( "The view cannot be null in the activity "+getClass().getSimpleName());
        }

        // This activity is the view's delegate
        try {
            this.view.setDelegate( (D)this );
        }
        catch ( Throwable e ) {
            throw new IllegalStateException( "Impossible to set the activity "+getClass().getSimpleName()+ " to the view "+this.view.getClass().getSimpleName(), e );
        }
    }

    /**
     * Inits the requestFactory
     */
    protected abstract void initRequestFactory();


    /**
     * Called when the Activity's widget has been removed from view.
     * All event handlers it registered will have been removed before this method is called.
     */
    @Override
    public void onStop() {
        super.onStop();
        this.display = null;
    }

    /**
     * Called when start has not yet replied to its callback, but the user has lost interest.
     */
    @Override
    public void onCancel() {
        // Par défaut, on appelle onStop
        onStop();
    }

    /**
     * Méthode lors de l'affichage de l'activité. La gestion de l'affichage est gérée directement
     */
    @Override
    public final void start( final AcceptsOneWidget pDisplayIn, final EventBus pEventBus ) {
        this.display = pDisplayIn;
        this.display.setWidget( this.view );
        this.eventBus = pEventBus;
        doStart();

        // On focuse le widget à l'affichage de la page, si un widget qui doit être focusé est défini dans la vue
        if ( this.view.getFocusedWidget() != null ) {
            Scheduler.get().scheduleDeferred( new Command() {

                @Override
                public void execute() {
                    PageAbstractActivity.this.view.getFocusedWidget().setFocus( true );
                }
            } );
        }
    }

    /**
     * Méthode exécutée à chaque fois qu'on affiche l'activité, l'affichage ayant été préalablement géré
     * @param pDisplayIn
     * @param pEventBus
     */
    protected abstract void doStart();

    /**
     * The place linked to the activity
     * @return
     */
    public abstract Place getPlace();
}
